#include <stdio.h>
#include <stdlib.h>
#include "tinfl.c"

static int tinfl_put_buf_func(const void* pBuf, int len, void *pUser)
{
  return len == (int)fwrite(pBuf, 1, len, (FILE*)pUser);
}

int main(int argc, char *argv[]) {
	int status;
	FILE *pInfile, *pOutfile;
	unsigned int infile_size, outfile_size;
	size_t in_buf_size;
	unsigned char *pCmp_data;

	if (argc < 3) {
		fprintf(stderr, "Usage: %s <infile.swf> <outfile.swf>\n", argv[0]);
		return EXIT_FAILURE;
	}

	// Open input file.
	pInfile = fopen(argv[1], "rb");
	if (!pInfile) {
		fprintf(stderr, "Error while opening: %s\n", argv[1]);
		return EXIT_FAILURE;
	}

	// Determine input file's size.
	fseek(pInfile, 0, SEEK_END);
	infile_size = ftell(pInfile);
	printf("Input file size: %u\n", infile_size);
	fseek(pInfile, 0, SEEK_SET);

	pCmp_data = (unsigned char *)malloc(infile_size);
	if (!pCmp_data) {
		fprintf(stderr, "Out of memory!\n");
		fclose(pInfile);
		return EXIT_FAILURE;
	}
	if (fread(pCmp_data, 1, infile_size, pInfile) != infile_size) {
		fprintf(stderr, "Error while reading: %s\n", argv[1]);
		fclose(pInfile);
		return EXIT_FAILURE;
	}

	// check signature
	if (!(pCmp_data[0] == 'C' && pCmp_data[1] == 'W' && pCmp_data[2] == 'S')) {
		fprintf(stderr, "Not valid compressed swf!\n");
		fclose(pInfile);
		return EXIT_FAILURE;
	}

	// get uncompressed file length
	outfile_size = pCmp_data[4] | (pCmp_data[5] << 8) | (pCmp_data[6] << 16) | (pCmp_data[7] << 24);
	printf("Uncompressed file size: %u\n", outfile_size);

	// Open output file.
	pOutfile = fopen(argv[2], "wb");
	if (!pOutfile) {
		fprintf(stderr, "Error while opening: %s\n", argv[2]);
		fclose(pInfile);
		return EXIT_FAILURE;
	}

	// write header
	pCmp_data[0] = 'F';
	pCmp_data[4] = outfile_size;
	pCmp_data[5] = outfile_size >> 8;
	pCmp_data[6] = outfile_size >> 16;
	pCmp_data[7] = outfile_size >> 24;
	fwrite(pCmp_data, 1, 8, pOutfile);

	in_buf_size = infile_size;
	status = tinfl_decompress_mem_to_callback(pCmp_data+8, &in_buf_size, tinfl_put_buf_func, pOutfile, TINFL_FLAG_PARSE_ZLIB_HEADER);
	if (!status) {
		fprintf(stderr, "tinfl_decompress_mem_to_callback() failed with status %i!\n", status);
		fclose(pInfile);
		fclose(pOutfile);
		return EXIT_FAILURE;
	}

	if (outfile_size != ftell(pOutfile)) {
		fprintf(stderr, "File size missmatch!\n");
		fclose(pInfile);
		fclose(pOutfile);
		return EXIT_FAILURE;
	}

	fclose(pInfile);
	if (EOF == fclose(pOutfile)) {
		fprintf(stderr, "Failed writing to output file!\n");
		return EXIT_FAILURE;
	}

	printf("Total input bytes: %u\n", (unsigned int)in_buf_size);
	printf("Total output bytes: %u\n", outfile_size);
	
	return EXIT_SUCCESS;
}
